package com.zodiac.alioth.web.exception;

import com.zodiac.alioth.common.enums.ApiRespCodeEnum;
import com.zodiac.alioth.common.model.vo.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.BindingException;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.net.ConnectException;
import java.sql.SQLException;

/**
 * @author insight
 */
@Slf4j
@RestControllerAdvice(annotations = {RestController.class, Controller.class})
public class SpringExceptionHandle {

    /**
     * 请求参数类型错误异常的捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {BindException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ApiResponse<String> badRequest(BindException e) {
        log.error("occurs error when execute method ,message {}", e.getMessage(), e);
        return ApiResponse.getResult(ApiRespCodeEnum.BAD_REQUEST);
    }

    /**
     * 404错误异常的捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {NoHandlerFoundException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public ApiResponse<String> badRequestNotFound(BindException e) {
        log.error("occurs error when execute method ,message {}", e.getMessage(), e);
        return ApiResponse.getResult(ApiRespCodeEnum.NOT_FOUND);
    }

    /**
     * mybatis未绑定异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BindingException.class)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<String> mybatis(Exception e) {
        log.error("occurs error when execute method ,message {}", e.getMessage(), e);
        return ApiResponse.getResult(ApiRespCodeEnum.BOUND_STATEMENT_NOT_FOUNT);
    }

    /**
     * 自定义异常的捕获
     * 自定义抛出异常。统一的在这里捕获返回JSON格式的友好提示。
     *
     * @param exception
     * @param request
     * @return
     */
    @ExceptionHandler(value = {AppException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public <T> ApiResponse<T> sendError(AppException exception, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("occurs error when execute url ={} ,message {}", requestURI, exception.getMessage());
        return ApiResponse.getResult(ApiRespCodeEnum.BAD_REQUEST);
    }

    /**
     * 自定义异常的捕获
     * 自定义抛出异常。统一的在这里捕获返回JSON格式的友好提示。
     *
     * @param exception
     * @param request
     * @return
     */
    @ExceptionHandler(value = {AuthException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.FORBIDDEN)
    public <T> ApiResponse<T> authError(AuthException exception, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("occurs error when execute url ={} ,message {}", requestURI, exception.getMessage());
        return ApiResponse.getResult(ApiRespCodeEnum.FORBIDDEN);
    }

    /**
     * 数据库操作出现异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {SQLException.class, DataAccessException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<String> systemError(Exception e) {
        log.error("occurs error when execute method ,message {}", e.getMessage(), e);
        return ApiResponse.getResult(ApiRespCodeEnum.DATABASE_ERROR);
    }

    /**
     * 网络连接失败！
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {ConnectException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<String> connect(Exception e) {
        log.error("occurs error when execute method ,message {}", e.getMessage(), e);
        return ApiResponse.getResult(ApiRespCodeEnum.CONNECTION_ERROR);
    }

    @ExceptionHandler(value = {Exception.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<String> notAllowed(Exception e) {
        log.error("occurs error when execute method ,message {}", e.getMessage(), e);
        return ApiResponse.getResult(ApiRespCodeEnum.ERROR);
    }

}
